package pathways.marvin_test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import pathways.CEnzyme;
import pathways.CEnzymePainter;
import pathways.CPathway;
import pathways.CReaction;
import pathways.CSubstrate;
import pathways.Database.Implementation.CDatabase;
import pathways.util.CUtil;
import chemaxon.formats.MolImporter;
import chemaxon.marvin.beans.MViewPane;
import chemaxon.struc.MolAtom;
import chemaxon.struc.Molecule;


/**
 * Title:
 * Description:
 * Copyright:    Copyright (c) 2001
 * Company:
 * @author Jia An Chen
 * @version 1.0
 */

public class AtomTraceSearchFrame extends JFrame {

  private JPanel mainPanel;
  private Vector molecules = new Vector();
  private Vector viewers = new Vector();
//  private CSubstrate[] m_substrates;
  private Vector tracableSubstrates = new Vector();
  private Hashtable moleculeTable = new Hashtable();
  private CPathway pathway;

  private JTextField atomNumTextField = new JTextField(5);
  private JComboBox molComboBox = new JComboBox();
  private int selectedViewer = 0;
  private CDatabase db;
  private Point pointOffset;

  public AtomTraceSearchFrame(CPathway p, CDatabase dataBase) {
    this("Atom Trace Search Window", p,dataBase);
  }

  public AtomTraceSearchFrame(String title, CPathway p, CDatabase dataBase) {
    super(title);
    this.pathway = p;
    this.db = dataBase;

    Vector substrates = this.pathway.getSubstrateList();
//    m_substrates = new CSubstrate[substrates.size()];
    InputStream inputFile;
    MolImporter mi;

    JPanel viewerPanel = null;
    mainPanel = new JPanel();
    mainPanel.setLayout(null);

    CSubstrate substrate = null;
    int mainPanelWidth = 0;
    int mainPanelHeight = 0;
    for (int i = 0; i < substrates.size(); i++) {
      substrate = (CSubstrate)((LinkedList)substrates.get(i)).get(0);
//      m_substrates[i] = substrate;

      inputFile = substrate.getFile();

      viewerPanel = new JPanel(new BorderLayout());
      if (inputFile != null) {
        this.molComboBox.addItem(substrate.getID() + ": " + substrate.getName());

        this.tracableSubstrates.add(substrate);

        Molecule molecule = null;
        try {
          mi = new MolImporter(inputFile);
          molecule = mi.read();
        }
        catch(Exception ex) {
          ex.printStackTrace();
          JOptionPane.showMessageDialog(this, ex.toString(), "Exception Thrown", JOptionPane.INFORMATION_MESSAGE);
          return;
        }

        molecules.add(molecule);

        MViewPane viewer = new ConfiguredMarvinPane();
        viewer.setM(0, molecule);
        viewer.setSelectable(false);
        viewer.addMouseListener(new ViewPanelMouseListener(this, i));
        viewers.add(viewer);

        moleculeTable.put(new Long(substrate.getID()), molecule);

        viewerPanel.add(new JLabel(substrate.getName(), JLabel.CENTER), BorderLayout.NORTH);
        viewerPanel.add(viewer, BorderLayout.CENTER);
      }
      else {
        JLabel lb = new JLabel(substrate.getName(), JLabel.CENTER);
        viewerPanel.add(lb, BorderLayout.CENTER);
        viewerPanel.setBackground(Color.black);
        lb.setBackground(Color.black);
        lb.setForeground(Color.white);
      }

      pointOffset = CUtil.getSmallestXandYOfSubs(pathway);

      Rectangle rect = substrate.getRect();
      viewerPanel.setSize(new Dimension(rect.width * 2, rect.height * 2));

      mainPanel.add(viewerPanel);
      viewerPanel.setLocation((rect.x - pointOffset.x) * 2 , (rect.y - pointOffset.y) * 2);

      int tempWidth = (rect.x - pointOffset.x + rect.width) * 2 + 15;
      if (mainPanelWidth < tempWidth)
        mainPanelWidth = tempWidth;
      int tempHeight = (rect.y - pointOffset.y + rect.height) * 2 + 15;
      if (mainPanelHeight < tempHeight) {
        mainPanelHeight = tempHeight;
      }
    }

    if (viewers.size() > 0) {
      ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectable(true);
      ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectedIndex(0);
    }

    mainPanel.setPreferredSize(new Dimension(mainPanelWidth, mainPanelHeight));

    JScrollPane jsp = new JScrollPane(mainPanel);
    jsp.setPreferredSize(new Dimension(480, 300));
    jsp.getHorizontalScrollBar().setUnitIncrement(20);
    jsp.getVerticalScrollBar().setUnitIncrement(20);

    jsp.getViewport().addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        AtomTraceSearchFrame.this.repaint();
      }
    });

    Container contentPane = this.getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(jsp, BorderLayout.CENTER);

    this.molComboBox.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        AtomTraceSearchFrame.this.viewerSelected();
      }
    });
    JPanel commandPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    commandPanel.add(this.molComboBox);

    commandPanel.add(new JLabel("Atom Number:"));

    ActionListener startTraceListener = new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        AtomTraceSearchFrame.this.startTracing();
      }
    };

    this.atomNumTextField.addActionListener(startTraceListener);
    commandPanel.add(this.atomNumTextField);

    JButton traceButton = new JButton("Trace");
    traceButton.addActionListener(startTraceListener);
    commandPanel.add(traceButton);

    contentPane.add(commandPanel, BorderLayout.SOUTH);

    this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  }

  public void viewerSelected() {
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectedIndex(-1);
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectable(false);

    this.selectedViewer = this.molComboBox.getSelectedIndex();
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectable(true);
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectedIndex(0);
  }

  public void viewerSelected(int selectedViewer) {
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectedIndex(-1);
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectable(false);

    this.selectedViewer = selectedViewer;
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectable(true);
    ((MViewPane)this.viewers.get(this.selectedViewer)).setSelectedIndex(0);
    this.molComboBox.setSelectedIndex(this.selectedViewer);
  }

  protected void startTracing() {
    if (this.tracableSubstrates.size() > 0) {
      int atomNum = 0;
      try {
        atomNum = Integer.parseInt(this.atomNumTextField.getText());
      }
      catch (NumberFormatException nfe) {
        JOptionPane.showMessageDialog(this, "Please enter an integer in the \"Atom Number\" text field.", "Alert Window", JOptionPane.ERROR_MESSAGE);
        return;
      }

      for (int i = 0; i < molecules.size(); i++) {
        ((Molecule)molecules.get(i)).setSetSeqs(0);
      }

      IAtomTraceDatabase database = CAtomTraceDatabase.create(db);
/*      System.out.println(this.pathway);
      System.out.println(this.m_substrates.length);
      System.out.println(atomNum);
*/
//      Vector cTraces = database.getAtomTraces(this.pathway, this.m_substrates[this.selectedViewer], atomNum);
      Vector cTraces = database.getAtomTraces(this.pathway, (CSubstrate)this.tracableSubstrates.get(this.selectedViewer), atomNum);
      CTraceMolecule trace;
      MolAtom atom;
      System.out.println(cTraces.size());
      try {
        for (int i = 0; i < cTraces.size(); i++) {
          trace = (CTraceMolecule)cTraces.elementAt(i);
          atom = ((Molecule)this.moleculeTable.get(new Long(trace.getMoleculeID()))).getAtom(trace.getAtomNum()-1);
          atom.setSetSeq(1);
        }
      }
      catch (ArrayIndexOutOfBoundsException aioobe) {
        JOptionPane.showMessageDialog(this, "Atom number doesn't exist in the selected molecule.", "Alert Window", JOptionPane.ERROR_MESSAGE);
        return;
      }

      this.repaint();
    }
    else {
      JOptionPane.showMessageDialog(this, "No tracable molecules are presented.", "Alert Window", JOptionPane.ERROR_MESSAGE);
      return;
    }
  }

  public void paint(Graphics g) {

    super.paint(g);
    Vector rxns = this.pathway.getReactions();
    CEnzymePainter enzymePainter = new CEnzymePainter();
    Graphics graphics = mainPanel.getGraphics();

    for (int i = 0; i < rxns.size(); i++) {
      CEnzyme enzyme = ((CReaction)rxns.get(i)).getEnzyme();
      Point oldPoint1 = enzyme.getPoint1();
      Point oldPoint2 = enzyme.getPoint2();
      enzyme.setPoint1(new Point((oldPoint1.x - pointOffset.x) * 2, (oldPoint1.y - pointOffset.y) * 2));
      enzyme.setPoint2(new Point((oldPoint2.x - pointOffset.x) * 2, (oldPoint2.y - pointOffset.y) * 2));

      enzyme.setPainter(enzymePainter);
      enzyme.draw(graphics, enzymePainter);

      enzyme.setPoint1(oldPoint1);
      enzyme.setPoint2(oldPoint2);
    }
  }

  //VJ???
  public static void main(String[] args) {
    /*CPathway p = new CPathway();
    CSubstrate s = new CSubstrate("fdsa", 323, new Rectangle(200, 5, 150, 150));
    p.addReaction(new CReaction(new CSubstrate("asdf", 123, new Rectangle(5, 5, 150, 150)), new CEnzyme("enzyme", 21), s, 2, 0));
    p.addReaction(new CReaction(s, new CEnzyme("ensfgzyme", 22), new CSubstrate("ffdsdsa", 3223, new Rectangle(400, 5, 150, 150)), 2, 0));
    JFrame mainFrame = new AtomTraceSearchFrame(p);
    mainFrame.setLocation(300, 300);
    mainFrame.pack();
    mainFrame.show();*/
  }

}
